package org.msb.accentis.gui;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.TimerTask;

import org.msb.accentis.data.DataManagerFactory;
import org.msb.accentis.data.Database;
import org.msb.accentis.data.IDataManager;
import org.msb.accentis.data.IDataManagerFactoryListener;
import org.msb.accentis.data.pojo.Schedule;
import org.msb.accentis.data.pojo.ScheduledTransaction;
import org.msb.accentis.data.pojo.Transaction;
import org.msb.accentis.data.pojo.TransactionDetail;
import org.msb.accentis.data.util.ScheduleHelper;
import org.msb.accentis.utils.DateUtils;

public class EnterScheduledTransactionsInRegisterTask extends TimerTask implements IDataManagerFactoryListener {

	private IDataManager dataManager;
	
	public EnterScheduledTransactionsInRegisterTask() {
		super();
		
		DataManagerFactory.getInstance().addDataManagerFactoryListener(this);
	}
	
	@Override
	public void run() {
		if (null == dataManager)
			return;
		
		List<ScheduledTransaction> results = dataManager.runNamedQuery("ScheduledTransaction.getAllScheduledTransactionsToEnterInRegister"); //$NON-NLS-1$
		for (ScheduledTransaction transaction : results)
			processScheduledTransaction(transaction);
	}
	
	protected void processScheduledTransaction(ScheduledTransaction transaction) {
		Integer advancedDays = transaction.getEnterInRegisterAdvancedDays();
		if (null == advancedDays)
			return;
		
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(DateUtils.createTodayMidnight());
		calendar.add(Calendar.DAY_OF_YEAR, -advancedDays);
		final Date thresholdDate = calendar.getTime();
		
		Date date = ScheduleHelper.calculateNextDate(transaction.getLastEntryDate(), transaction);
		while (!date.after(thresholdDate) && !haveMaximumOccurrencesHappened(transaction.getSchedule(), transaction.getEntryCount())) {
			enterTransactionInRegister(transaction, date);
			
			date = ScheduleHelper.calculateNextDate(date, transaction);
		}
	}
	
	private boolean haveMaximumOccurrencesHappened(Schedule schedule, int entryCount) {
		Integer occurrences = schedule.getEndsOccurrences();
		if (null == occurrences)
			return false;
		
		return occurrences.intValue() <= entryCount;
	}
	
	protected void enterTransactionInRegister(ScheduledTransaction transaction, Date date) {
		Transaction enteredTransaction = new Transaction();
		enteredTransaction.setDate(date);
		enteredTransaction.setDescription(transaction.getTransactionDescription());
		enteredTransaction.setPayee(transaction.getTransactionPayee());
		enteredTransaction.setReference(transaction.getTransactionReference());
		for (TransactionDetail detail : transaction.getTransactionDetails())
			enteredTransaction.getTransactionDetails().add(detail);
		
		dataManager.persist(enteredTransaction);
		
		transaction.setLastEntryDate(date);
		dataManager.save(transaction);
	}

	@Override
	public void databaseChanged(Database database) {
		if (null != database)
			dataManager = database.getDataManager();
	}

	void setDataManager(IDataManager value) {
		dataManager = value;
	}
}
